package seedpod.kb2db;
/**
 * Copyright 2009 University of  Washington
 * This code is released under the GPL version 3 - with a copy of the license included
 * @author Maya Hao Li
 *
 */
import java.util.ArrayList;
import java.util.Iterator;
import edu.stanford.smi.protege.model.KnowledgeBase;
import edu.stanford.smi.protege.model.Project;
import edu.stanford.smi.protege.storage.clips.ClipsKnowledgeBaseFactory;
import edu.stanford.smi.protege.util.PropertyList;
import edu.stanford.smi.protege.util.URIUtilities;

public class ProjectTransformValidator
{
	private Project _project;
	private KnowledgeBase _kb;
	private ArrayList<String> _errors = new ArrayList<String>();
	private ArrayList<Rule> _rules = new ArrayList<Rule>();

	{
		Rule rule_0 = new Rule( "Clips KnowledgeBase Required" ) {
			public boolean test() throws InvalidClassTypeException {
				if ( !isProjectFilePprj( _project ) || !isClipsKB( _project ) )
					throw new InvalidClassTypeException();
				else
					return true;
			}
		};

		Rule rule_1 = new Rule( "Default Rdb_Cls MetaCls Rule" ) {
			public boolean test() throws ExpectedMetaclsMissingException {
				if ( !hasClsMetaCls( Protege2Rdb.DEFAULT_META_RDB_CLS ) )
					throw new ExpectedMetaclsMissingException( Protege2Rdb.DEFAULT_META_RDB_CLS );
				else
					return true;
			}
		};
		
		Rule rule_2 = new Rule( "Default Rdb_Slot MetaCls Rule" ) {
			public boolean test() throws ExpectedMetaclsMissingException {
				if ( !hasClsMetaCls( Protege2Rdb.DEFAULT_META_RDB_SLOT ) )
					throw new ExpectedMetaclsMissingException( Protege2Rdb.DEFAULT_META_RDB_SLOT );
				else
					return true;
			}
		};

		addRule( rule_0 );
		addRule( rule_1 );
		addRule( rule_2 );		
	}

	public ProjectTransformValidator(KnowledgeBase kb) {
		_kb = kb;
		_project = kb.getProject();
	}

	public Project getProject() {
		return _project;
	}

	public void addRule( Rule rule ) {
		_rules.add( rule );
	}

	public boolean validateKB() throws TransformValidationException{
		boolean valid = true;

		for ( Iterator<Rule> iter = _rules.iterator(); iter.hasNext(); ) {
			Rule r = (Rule)iter.next();
				r.test();
		}

		if ( _errors.size() > 0 )
			valid = false;
		return valid;
	}

	public static boolean isClipsKB( Project p ) {
		PropertyList sources = p.getSources();
		String kbFactory = sources.getString( ClipsKnowledgeBaseFactory.FACTORY_CLASS_NAME );
		return (kbFactory.compareTo( ClipsKnowledgeBaseFactory.class.getName() ) == 0);
	}

	public static boolean isProjectFilePprj( Project p ) {
		String extension = "." + URIUtilities.getExtension( p.getProjectURI() );
		return ( extension.endsWith( Protege2Rdb.VALID_EXTENSION ));
	}

	protected boolean hasClsMetaCls( String metaClsName ) {
		return _kb.getCls( metaClsName ) != null;
	}

	public ArrayList<String> getErrors() {
		return _errors;
	}

	abstract class Rule
	{
		private String _ruleName;

		public Rule() {}

		public Rule(String ruleName) {
			_ruleName = ruleName;
		}
		
		public String getRuleName() {
			return _ruleName;
		}

		public abstract boolean test() throws TransformValidationException;
	}

	public class TransformValidationException extends Exception {
		private static final long serialVersionUID = 1L;
		public TransformValidationException( String msg) {
			super( msg );
		}
	}
	
	public class InvalidClassTypeException extends TransformValidationException
	{
		private static final long serialVersionUID = 1L;

		public InvalidClassTypeException() {
			super( "Invalid project extension " + Protege2Rdb.VALID_EXTENSION + " only." );
			_errors.add( getMessage() );
		}

		public InvalidClassTypeException(String msg) {
			super( msg );
		}
	}
	
	
	public class ExpectedMetaclsMissingException extends TransformValidationException
	{
		private static final long serialVersionUID = 1L;

		public ExpectedMetaclsMissingException() {
			super( "Missing metacls" );
			_errors.add( getMessage() );
		}

		public ExpectedMetaclsMissingException(String clsName) {
			super( "Missing metacls " + clsName );
			_errors.add( getMessage() );
		}
	}

}
